package com.hins.component.hlock;

import com.hins.component.hlock.config.HlockConfig;
import com.hins.component.hlock.core.BusinessKeyProvider;
import com.hins.component.hlock.core.HlockAspectHandler;
import com.hins.component.hlock.core.LockInfoProvider;
import com.hins.component.hlock.lock.LockFactory;
import io.netty.channel.nio.NioEventLoopGroup;
import lombok.Setter;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ClassUtils;

import java.util.Objects;

/**
 * hlock自动装配
 *
 * @author Leslie
 * @date 2021/9/7 9:32
 */
@Configuration
@ConditionalOnProperty(prefix = HlockConfig.PREFIX, name = "enable", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableConfigurationProperties(HlockConfig.class)
@Import({HlockAspectHandler.class})
public class HlockAutoConfiguration {

    @Setter(onMethod = @__(@Autowired))
    private HlockConfig hlockConfig;

    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean
    RedissonClient redisson() throws Exception {
        Config config = new Config();
        if (Objects.nonNull(hlockConfig.getClusterServer())) {
            config.useClusterServers().addNodeAddress(hlockConfig.getClusterServer().getNodeAddresses()).setPassword(hlockConfig.getPassword());
        } else {
            config.useSingleServer().setAddress(hlockConfig.getAddress()).setDatabase(hlockConfig.getDatabase()).setPassword(hlockConfig.getPassword());
        }
        Codec codec = (Codec) ClassUtils.forName(hlockConfig.getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
        config.setCodec(codec);
        config.setEventLoopGroup(new NioEventLoopGroup());
        return Redisson.create(config);
    }

    @Bean
    public LockInfoProvider lockInfoProvider() {
        return new LockInfoProvider();
    }

    @Bean
    public BusinessKeyProvider businessKeyProvider() {
        return new BusinessKeyProvider();
    }

    @Bean
    public LockFactory lockFactory() {
        return new LockFactory();
    }
}
